{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Feature Calculator Settings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, all feature calculators are used when you call `extract_features`.\n",
    "There could be multiple reasons why you do not want that:\n",
    "* you are only interested on a certain feature (or features)\n",
    "* you want to save time during extraction\n",
    "* you have ran the feature selection before and already know, which features are relevant\n",
    "\n",
    "For more information on these settings, please have a look into [the documentation](http://tsfresh.readthedocs.io/en/latest/text/feature_extraction_settings.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tsfresh.feature_extraction import extract_features\n",
    "from tsfresh.feature_extraction import settings\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Construct a time series container"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For testing, we construct the time series container that includes two sensor time series, \"temperature\" and \"pressure\", for two devices \"a\" and \"b\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\"id\": [\"a\", \"a\", \"b\", \"b\"], \"temperature\": [1,2,3,1], \"pressure\": [-1, 2, -1, 7]})\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `default_fc_parameters`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Which features are calculated by `tsfresh` is controlled by a dictionary that contains a mapping from feature calculator names to their parameters. \n",
    "This dictionary is called `fc_parameters`. \n",
    "It maps feature calculator names (= keys) to parameters (= values). \n",
    "Every key in the dictionary will be looked up as a function in `tsfresh.feature_extraction.feature_calculators` and be used to extract features.\n",
    "\n",
    "`tsfresh` comes with some predefined sets of `fc_parameters` dictionaries:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "settings.ComprehensiveFCParameters, settings.EfficientFCParameters, settings.MinimalFCParameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For example, to only calculate a very minimal set of features:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "settings_minimal = settings.MinimalFCParameters() \n",
    "settings_minimal"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each key stands for one of the feature calculators. \n",
    "The value are the parameters. If a feature calculator has no parameters, `None` is used as a value (and as these feature calculators are very simple, they all have no parameters)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This dictionary can passed to the extract method, resulting in a few basic time series beeing calculated:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_tsfresh = extract_features(df, column_id=\"id\", default_fc_parameters=settings_minimal)\n",
    "X_tsfresh.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By using the settings_minimal as value of the default_fc_parameters parameter, those settings are used for all type of time series. \n",
    "In this case, the `settings_minimal` dictionary is used for both \"temperature\" and \"pressure\" time series.\n",
    "\n",
    "Please note how the columns in the resulting dataframe depend both on the settings as well as the kinds of the data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, lets say we want to remove the length feature and prevent it from beeing calculated. We just delete it from the dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "del settings_minimal[\"length\"]\n",
    "settings_minimal"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, if we extract features for this reduced dictionary, the length feature will not be calculated"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_tsfresh = extract_features(df, column_id=\"id\", default_fc_parameters=settings_minimal)\n",
    "X_tsfresh.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `kind_to_fc_parameters`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, lets say we do not want to calculate the same features for both type of time series. Instead there should be different sets of features for each kind.\n",
    "\n",
    "To do that, we can use the `kind_to_fc_parameters` parameter, which lets us specifiy which `fc_parameters` we want to use for which kind of time series:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fc_parameters_pressure = {\"length\": None, \n",
    "                          \"sum_values\": None}\n",
    "\n",
    "fc_parameters_temperature = {\"maximum\": None, \n",
    "                             \"minimum\": None}\n",
    "\n",
    "kind_to_fc_parameters = {\n",
    "    \"temperature\": fc_parameters_temperature,\n",
    "    \"pressure\": fc_parameters_pressure\n",
    "}\n",
    "\n",
    "print(kind_to_fc_parameters)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So, in this case, for sensor \"pressure\" both \"max\" and \"min\" are calculated. \n",
    "For the \"temperature\" signal, the length and sum\\_values features are extracted instead."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_tsfresh = extract_features(df, column_id=\"id\", kind_to_fc_parameters=kind_to_fc_parameters)\n",
    "X_tsfresh.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Extracting from data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After applying a feature selection algorithm to drop irrelevant feature columns you know which features are relevant and which are not.\n",
    "You can also use this information to only extract these relevant features in the first place.\n",
    "\n",
    "The provided `from_columns` method can be used to infer a settings dictionary from the dataframe containing the features.\n",
    "This dictionary can then for example be stored and be used in the next feature extraction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Assuming `X_tsfresh` contains only our relevant features\n",
    "relevant_settings = settings.from_columns(X_tsfresh)\n",
    "relevant_settings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## More complex dictionaries"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We provide `fc_parameters` dictionaries with larger sets of features.\n",
    "\n",
    "The `EfficientFCParameters` contain features and parameters that should be calculated quite fast:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "settings_efficient = settings.EfficientFCParameters()\n",
    "settings_efficient"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `ComprehensiveFCParameters` are the biggest set of features. It will take the longest to calculate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "settings_comprehensive = settings.ComprehensiveFCParameters()\n",
    "settings_comprehensive"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature Calculator Parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "More complex feature calculators have parameters that you can use to tune the extracted features.\n",
    "The predefined settings (such as `ComprehensiveFCParameters`) already contain default values of these features.\n",
    "\n",
    "However for your own projects, you might want/need to tune them.\n",
    "\n",
    "In detail, the values in a `fc_parameters` dictionary contain a list of parameter dictionaries. \n",
    "When calculating the feature, each entry in the list of parameters will be used to calculate one feature.\n",
    "\n",
    "For example, lets have a look into the feature `large_standard_deviation`, which depends on a single parameter called `r` (it basically defines how large \"large\" is).\n",
    "The `ComprehensiveFCParameters` contains several default values for `r`. \n",
    "Each of them will be used to calculate a single feature:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "settings_comprehensive['large_standard_deviation']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you use these settings in feature extraction, that would trigger the calculation of 20 different `large_standard_deviation` features, one for `r=0.05` up to `r=0.95`.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "settings_tmp = {'large_standard_deviation': settings_comprehensive['large_standard_deviation']}\n",
    "\n",
    "X_tsfresh = extract_features(df, column_id=\"id\", default_fc_parameters=settings_tmp)\n",
    "X_tsfresh.columns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you now want to change the parameters for a specific feature calculator, all you need to do is to change the dictionary values."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
